//
//  ThreeTManager.swift
//  jiahui
//
//  Created by 3tee on 2024/12/5.
//

import UIKit
import avd_sdk
import RxSwift
import ReactiveSwift
class ThreeTManager: NSObject {
    static let shardInstance = ThreeTManager()
    var joinComplete: BoolBlock?
    private(set) var mRoom: AVDRoom?
    private(set) var mVideo: AVDVideo?
    private(set) var mAudio: AVDAudio?
    private(set) var mChat: AVDChat?
    private(set) var mUserManager: AVDUserManager?
    private(set) var cameraOpenNoti = PublishSubject<String>()//远端发布摄像头observeable
    private(set) var cameraCloseNoti = PublishSubject<String>()//远端关闭摄像头observeable
    private(set) var localCameraOpenNoti = BehaviorSubject<String>(value: "")//本地发布摄像头observeable
    private(set) var localCameraCloseNoti = PublishSubject<String>()//本地关闭摄像头observeable
    private(set) var msgReceiveNoti = PublishSubject<AVDMessage>()//远端发布摄像头observeable

    fileprivate var mRenders: [String: AVDVideoView] = [String: AVDVideoView]()
    fileprivate var openVideo: Bool?
    fileprivate var openAudio: Bool?
    private(set) var isInit = false
    
    deinit {
        print("\(self) delloc")
    }
    
    func initEng(WithUrl url: String, access: String = "demo_access",secret: String = "demo_secret") -> Void {
        AVDEngine.instance().initWithServerUrl(url, accessKey: access, secretKey: secret, delegate: self)
    }
    func joinRoom(_ roomId: String,_ name: String, userid: String, videoOn :Bool = false ,audioOn: Bool = false,  complete: @escaping BoolBlock){
        guard isInit else {
            return
        }
        openAudio = audioOn
        openVideo = videoOn
        joinComplete = complete
        mRoom = AVDRoom.obtain(roomId)
        let uid = userid.isEmpty ?  UUID().uuidString : userid
        let user = AVDUser(userId:uid, userName: name, userData: nil)
        mRoom?.join(with: user, delegate: self)
    }
    
    func leaveRoom() {
        mRenders.removeAll()
        mRoom?.leave(0)
        mRoom?.destory()
        mRoom = nil
    }
    
    func switchCramera() -> Void {
        mVideo?.switchToLocalCamera()
    }
    
    func speakerMode(_ mode: Int) {
        let model = mode == 0 ? AVDSpeakerMode(rawValue: 0) : AVDSpeakerMode(rawValue: 1)
        mAudio?.setSpeakerMode(model)
    }
    
    func openMic(isOpen: Bool){
       _ = isOpen ? mAudio?.openMicrophone() : mAudio?.closeMicrophone()
    }
    
    func openCamera(_ isOpen: Bool) {
        _ = isOpen ? mVideo?.publishLocalCamera() : mVideo?.unpublishLocalCamera()
    }
    
    func subscribe(deviceId: String){
        mVideo?.subscribe(deviceId)
    }
    
    func sendMsg(_ msg: String) {
        
        mChat?.sendPublicMessage(msg)
        let model = MessageModel()
        model.userid = mUserManager?.selfUser.userId ?? ""
        model.content = msg
        model.fromName = mUserManager?.selfUser.userName ?? ""
        model.msgTime = Int64(Date().timeIntervalSince1970)
        model.key = model.userid + String(describing: model.msgTime)
        DBManager.shared.insert(objs: [model], tableName: "Message")
    }
    
    func attachRender(_ render: AVDVideoView) {
        if let deviceid = render.getVideoId(){
            guard deviceid != "" else{
                print("设备id为空直接跳过")
                return
            }
            if  mVideo?.isSelfDevice(deviceid) ?? false{//自己的摄像头默认订阅
                 mRenders[deviceid] = render
                 mVideo?.attachRender(withDeviceId: deviceid, render: render)
                return
            }
            
            if cameraSubList().contains(deviceid)  {
                print("当前设备id已经订阅过请直接渲染")
                mVideo?.attachRender(withDeviceId: deviceid, render: render)
                return
            }
            
//            mRenders[deviceid] = render
//            mVideo?.subscribe(deviceid)
        }
       
    }
    
    func detachRender(_ render: AVDVideoView) {
        
        if let did = render.getVideoId() {
           mRenders[did] = nil
            mVideo?.detachRender(withRender: render)
            //render!.setVideoId("")
        }
        //mVideo?.unsubscribe(render.getVideoId())
//        let render = mRenders[render.getVideoId()]
//        mVideo?.detachRender(withRender: render)
//        render!.setVideoId("")
    }
    
    func cameraPubList() -> [String] {
        if let list = mVideo?.publishedCameras as? [AVDCamera] {
            return list.map{$0.id}
        }
        return [String]()
    }
    
    func cameraSubList() -> [String] {
        if let list = mVideo?.subscribedCameras as? [AVDCamera] {
            return list.map{$0.id}
        }
        return [String]()
    }
}

extension ThreeTManager: AVDEngineDelegate{
    func onInitResult(_ result: AVDResult) {
       isInit = (result == AVD_Success)
       print("媒体引擎初始化 \(isInit ? "成功" : "失败 code = \(result)")")
    }
    
    func onUninitResult(_ result: AVDResult) {
        
    }
}

extension ThreeTManager: AVDRoomJoinDelegate{
    func onJoinResult(_ aResult: AVDResult) {
        print("加入会议 \(aResult == AVD_Success ? "成功" : "失败")")
        if aResult == AVD_Success{
            joinComplete!(aResult == AVD_Success)
            mVideo = AVDVideo.getVideo(mRoom)
            mVideo?.delegate = self
            mAudio = AVDAudio.getAudio(mRoom)
            mAudio?.delegate = self
            mUserManager = AVDUserManager.getUserManager(mRoom)
            mUserManager?.delegate = self
            mChat = AVDChat.getChat(mRoom)
            mChat?.delegate = self;
            if openAudio ?? false {
                mAudio?.openMicrophone()
            }
            if openVideo ?? false{
                mVideo?.publishLocalCamera()
            }
            mVideo?.publishedCameras.forEach({ avdcamer in
                let cam = avdcamer as! AVDCamera
                mVideo?.subscribe(cam.id)
            })
        }
    }
}


extension ThreeTManager: AVDVideoDelegate{
    func onCameraStatusNotify(_ status: AVDDeviceStatus, deviceId fromId: String!) {
        
    }
    
    func onPublishCameraNotify(_ camera: AVDCamera!) {
        if mVideo?.isSelfDevice(camera.id) ?? false {
            return
        }
        mVideo?.subscribe(camera.id)
    }
    
    func onUnpublishCameraNotify(_ camera: AVDCamera!) {
        if mVideo?.isSelfDevice(camera.id) ?? false {
            return
        }
        mVideo?.unsubscribe(camera.id)
    }
    
    func onPublishLocalResult(_ result: AVDResult, deviceId fromId: String!) {
        localCameraOpenNoti.onNext(fromId)
         let render = mRenders[fromId]
         mVideo?.attachRender(withDeviceId: fromId, render: render)
    }
    
    func onUnpublishLocalResult(_ result: AVDResult, deviceId fromId: String!) {
        localCameraCloseNoti.onNext(fromId)
    }
    
    func onSubscribeResult(_ result: AVDResult, deviceId fromId: String!) {
        print("当前渲染render = \(mRenders)")
        cameraOpenNoti.onNext(fromId)

       let render = mRenders[fromId]
        mVideo?.attachRender(withDeviceId: fromId, render: render)
    }
    
    func onUnsubscribeResult(_ result: AVDResult, deviceId fromId: String!) {
        cameraCloseNoti.onNext(fromId)
    }
}


extension ThreeTManager: AVDAudioDelegate{
    func onMicrophoneStatusNotify(_ status: AVDDeviceStatus, fromUser fromId: String!) {
        
    }
    
    
}

extension ThreeTManager: AVDUserManagerDelegate{
    func onUserJoinNotify(_ user: AVDUser!) {
        
    }
    
    func onUserLeaveNotify(_ user: AVDUser!) {
        
    }
    
    func onUserLeaveNotify(_ reason: AVDResult, leave user: AVDUser!) {
        
    }
    
    func onUserUpdateNotify(_ user: AVDUser!) {
        
    }
    
    func onUserStatusNotify(_ status: AVDUserStatus!, fromUser fromId: String!) {
        
    }
    
    func onUserDataNotify(_ userData: String!, fromUser fromId: String!) {
        
    }
    
    
}


extension ThreeTManager: AVDChatDelegate{
    func onPublicMessage(_ message: AVDMessage!) {
        msgReceiveNoti.onNext(message)
        let model = MessageModel()
        model.userid = message.fromId
        model.content = message.message
        model.msgTime = Int64(Date().timeIntervalSince1970)
        model.key = message.fromId + String(describing: model.msgTime)
        model.fromName = message.fromName
        DBManager.shared.insert(objs: [model], tableName: "Message")
    }
    
    func onPrivateMessage(_ message: AVDMessage!) {
        msgReceiveNoti.onNext(message)
        let model = MessageModel()
        model.userid = message.fromId
        model.content = message.message
        model.msgTime = Int64(Date().timeIntervalSince1970)
        DBManager.shared.insert(objs: [model], tableName: "Message")
    }
}
